#include <crtdbg.h>
#include <direct.h>
#include <stdio.h>

#include "toolbox_interchange.hpp"
#include "rdxsupport.hpp"
#include "../tdp2/tdp2_visualresources.hpp"
#include "../tdp2/tdp2_string.hpp"

using namespace RDX;
using namespace RDX::ObjectManagement;
using namespace RDX::Programmability;

// Merges primary lights into a map resource
int MergePL_Main()
{
	if(toolResources.argc >= 3 && !strcmp(toolResources.argv[2], "-rdxtextfirst"))
	{
		toolResources.argv++;
		toolResources.argc--;
	}

	if(toolResources.argc != 3)
	{
		fprintf(stderr, "Syntax: mergepl <map name>\n");
		fprintf(stderr, "        Merges additional metadata into a map resource and emits it as a binary");
		return -1;
	}

	{
		const char *mapName = toolResources.argv[2];

		RDX::OperationContext ctx(toolResources.objm);
		CRef<const String> str1 = toolResources.objm->CreateStringASCII(&ctx, "TDP.Resources.Maps.");
		CRef<const String> str2 = toolResources.objm->CreateStringASCII(&ctx, mapName);
		CRef<const String> symbolStr = toolResources.objm->CreateStringConcatenated(&ctx, str1, str2);
		str2 = toolResources.objm->CreateStringASCII(&ctx, ".Data.worldModel");
		symbolStr = toolResources.objm->CreateStringConcatenated(&ctx, symbolStr, str2);

		wprintf(L"Looking up symbol %s\n", symbolStr->AsChars());

		printf("%s loading ...", mapName);
		CRef<TDP::Resources::WorldModel> wm = toolResources.objm->LookupSymbol(&ctx, symbolStr, toolResources.pkgHost).ReinterpretCast<TDP::Resources::WorldModel>();
		if(wm == NULL)
		{
			fprintf(stderr, "\n\nCouldn't load package for %s", mapName);
			return -1;
		}

		printf("    Merging lights ...");
		{
			TDP::CString plPath(TDP::Memory::DefaultAllocator());
			plPath.Set(NULL, "maps/");
			plPath.Append(NULL, mapName);
			plPath.Append(NULL, "_photons/primarylights");

			FILE *plFile = fopen(plPath.Chars(), "rb");

			UInt32 numPLights = 0;
			fread(&numPLights, sizeof(numPLights), 1, plFile);

			if(numPLights != 0)
			{
				CRef<const String> plTypeName = toolResources.objm->CreateStringASCII(&ctx, "TDP.Resources.WorldModel.PrimaryLight").ReinterpretCast<const String>();
				CRef<Type> plType = toolResources.objm->LookupSymbol(&ctx, plTypeName, toolResources.pkgHost).ReinterpretCast<Type>();
				CRef<ArrayOfType> plConstAOT = toolResources.objm->CreateArrayType(&ctx, plType, 1, true);
				wm->primaryLights = toolResources.objm->Create1DArray<TDP::Resources::WorldModel::PrimaryLight>(&ctx, static_cast<LargeInt>(numPLights), plConstAOT.Object());

				for(UInt32 i=0;i<numPLights;i++)
					fread(wm->primaryLights + i, sizeof(wm->primaryLights[0]), 1, plFile);
			}

			UInt32 numMappings = 0;
			fread(&numMappings, sizeof(numMappings), 1, plFile);
			for(UInt32 i=0;i<numMappings;i++)
			{
				UInt32 modelIndex;
				UInt32 batchGroupIndex;
				UInt32 segmentIndex;
				Int32 plIndex;
				fread(&modelIndex, sizeof(modelIndex), 1, plFile);
				fread(&batchGroupIndex, sizeof(batchGroupIndex), 1, plFile);
				fread(&segmentIndex, sizeof(segmentIndex), 1, plFile);
				fread(&plIndex, sizeof(plIndex), 1, plFile);

				wm->models[modelIndex].clusterInfos[wm->models[modelIndex].firstCluster + batchGroupIndex].segmentInfos[segmentIndex].primaryLightIndex = static_cast<Int>(plIndex + 1);
			}


			fclose(plFile);
		}

		printf("    Saving ...");
		toolResources.objm->SavePackage(&ctx, GCInfo::From(wm)->domain, toolResources.pkgHost);
		printf("Done\n");

		return 0;
	}
}